#include <string.h>
        #include <assert.h>
        #include <iostream>
        
using namespace std;
        typedef double Coord;

        /*
        The type of X/Y points on the screen.
        */
        
        enum Color {Co_red, Co_green, Co_blue};

        /*
        Colors.
        */
        
        // abstract base class for all shape types
        class Shape {
        protected:
                Coord xorig; // X origin
                Coord yorig; // Y origin
                Color co; // color

        /*
        These are protected so that they can be accessed
        by derived classes.  Private wouldn't allow this.
        
        These data members are common to all shape types.
        */

        public:
                Shape(Coord x, Coord y, Color c) :
                    xorig(x), yorig(y), co(c) {} // constructor

        /*
        Constructor to initialize data members common to
        all shape types.
        */

                virtual ~Shape() {} // virtual destructor

        /*
        Destructor for Shape.  It's a virtual function.
        Destructors in derived classes are virtual also
        because this one is declared so.
        */

                virtual void draw() = 0; // pure virtual draw() function

        /*
        Similarly for the draw() function.  It's a pure virtual and
        is not called directly.
        */

        };
        
        // line with X,Y destination
        class Line : public Shape {

        /*
        Line is derived from Shape, and picks up its
        data members.
        */

                Coord xdest; // X destination
                Coord ydest; // Y destination

        /*
        Additional data members needed only for Lines.
        */

        public:
                Line(Coord x, Coord y, Color c, Coord xd, Coord yd) :
                    xdest(xd), ydest(yd),
                    Shape(x, y, c) {} // constructor with base initialization

        /*
        Construct a Line, calling the Shape constructor as well
        to initialize data members of the base class.
        */

                ~Line() {cout << "~Line\n";} // virtual destructor

        /*
        Destructor.
        */

                void draw() // virtual draw function
                {
                        cout << "Line" << "(";
                        cout << xorig << ", " << yorig << ", " << int(co);
                        cout << ", " << xdest << ", " << ydest;
                        cout << ")\n";
                }

        /*
        Draw a line.
        */

        };
        
        // circle with radius
        class Circle : public Shape {
                Coord rad; // radius of circle

        /*
        Radius of circle.
        */

        public:
                Circle(Coord x, Coord y, Color c, Coord r) : rad(r),
                    Shape(x, y, c) {} // constructor with base initialization

                ~Circle() {cout << "~Circle\n";} // virtual destructor
                void draw() // virtual draw function
                {
                        cout << "Circle" << "(";
                        cout << xorig << ", " << yorig << ", " << int(co);
                        cout << ", " << rad;
                        cout << ")\n";
                }
        };
        
        // text with characters given
        class Text : public Shape {
                char* str; // copy of string
        public:
                Text(Coord x, Coord y, Color c, const char* s) :
                    Shape(x, y, c) // constructor with base initialization
                {
                        str = new char[strlen(s) + 1];
                        assert(str);
                        strcpy(str, s);

        /*
        Copy out text string.  Note that this would be done differently
        if we were taking advantage of some newer C++ features like
        exceptions and strings.
        */

                }
                ~Text() {delete [] str; cout << "~Text\n";} // virtual dtor

        /*
        Destructor; delete text string.
        */

                void draw() // virtual draw function
                {
                        cout << "Text" << "(";
                        cout << xorig << ", " << yorig << ", " << int(co);
                        cout << ", " << str;
                        cout << ")\n";
                }
        };
        
        int main()
        {
                const int N = 5;
                int i;
                Shape* sptrs[N];

        /*
        Pointer to vector of Shape* pointers.  Pointers to classes
        derived from Shape can be assigned to Shape* pointers.
        */

                // initialize set of Shape object pointers
        
                sptrs[0] = new Line(0.1, 0.1, Co_blue, 0.4, 0.5);
                sptrs[1] = new Line(0.3, 0.2, Co_red, 0.9, 0.75);
                sptrs[2] = new Circle(0.5, 0.5, Co_green, 0.3);
                sptrs[3] = new Text(0.7, 0.4, Co_blue, "Howdy!");
                sptrs[4] = new Circle(0.3, 0.3, Co_red, 0.1);

        /*
        Create some shape objects.
        */

                // draw set of shape objects
        
                for (i = 0; i < N; i++)
                        sptrs[i]->draw();

        /*
        Draw them using virtual functions to pick up the
        right draw() function based on the actual object
        type being pointed at.
        */

                // cleanup
        
                for (i = 0; i < N; i++)
                        delete sptrs[i];        

        /*
        Clean up the objects using virtual destructors.
        */

                return 0;
        }